package com.ydc.ln.tutorial.gui.app.minieditor;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.FileDialog;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.BadLocationException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

/**
 * 主类，实现主要功能，并实现图形用户界面
 * 
 * @author ydc
 * @date 上午12:58:38 2013-4-13
 */
public class MiniEditor extends JFrame
        implements
            ActionListener,
            CaretListener,
            DocumentListener,
            KeyListener {

    /**
     * @Fields serialVersionUID
     */
    private static final long serialVersionUID = 5726461540338704871L;

    // 菜单项目
    JMenuItem menuFileNew, menuFileOpen, menuFileClose, menuFileSave,
            menuFileSaveAs, menuFilePrint, menuFilePrintSetup, menuFileExit,
            menuEditUndo, menuEditRedo, menuEditCut, menuEditCopy,
            menuEditPaste, menuEditDeleteSelection, menuEditDeleteLine,
            menuEditDeleteWord, menuEditFind, menuEditReplace, menuEditGoTo,
            menuEditSelectAll, menuViewFont, menuViewColor,
            menuViewDoubleSpace, menuHelpAbout;

    // 选项菜单
    JCheckBoxMenuItem menuViewClassic, menuViewStatus, menuViewWordWrap;

    // 可打印TextArea
    PrintableTextArea pta;
    TextField tfs, tfro, tfrn;

    // 状态栏标签
    Label fileStatus, statusRow, statusCol, statusMode, statusSize;

    // 弹出对话框按钮
    Button bs, brf, brr, brra;

    // 子Frame和JDialog实例
    JFrame fr;
    JDialog dl;

    // 其他组件
    String fns;

    Color defaultForeground, defaultBackground, defaultCaretColor;
    Font defaultFont = new Font("Courier", Font.PLAIN, 12);
    Checkbox dsLoop, dsMatchCase, drMatchCase;
    JLabel dsMessage2;

    // UndoManager
    protected UndoManager undo = new UndoManager();
    protected UndoableEditListener undoHandler = new UndoHandler();

    // 状态标记
    static int foundCount = 0;
    int FindStartPos = 0;
    boolean findingLoop = true;
    boolean beginTextListener, isNewFile;
    boolean INSERTMODE = true;
    boolean BACKSPACE = false;

    // 入口方法
    public static void main(String[] args) {
        try {
            // 选取不同LookAndFeel
            // com.sun.java.swing.plaf.motif.MOtifLookAndFeel
            // javax.swing.plaf.metal.MetalLookAndFeel
            UIManager
                    .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 设定Locale
        // Locale.setDefault(Locale.CHINA);
        // Locale.setDefault(new Locale("zh", "CN"));

        MiniEditor me = new MiniEditor();

        me.windowLayout();
    }

    // 窗体布局
    public void windowLayout() {
        // 初始化窗体
        JFrame fr = new JFrame("MiniEditor v1.0");
        fr.getContentPane().setLayout(new BorderLayout(5, 5));
        JPanel p = new JPanel();

        // 初始化状态栏
        fileStatus = new Label("File Status:    ");
        statusRow = new Label("Row:     ");
        statusCol = new Label("Col:     ");
        statusMode = new Label("Mode:   ");
        statusSize = new Label("Size:   ");

        // 初始化文本编辑框
        pta = new PrintableTextArea(20, 50);
        pta.setCursor(new Cursor(Cursor.HAND_CURSOR));
        pta.setFont(defaultFont);
        defaultForeground = pta.getForeground();
        defaultBackground = pta.getForeground();
        defaultCaretColor = pta.getCaretColor();
        pta.setWrapStyleWord(true);
        pta.getDocument().addDocumentListener(this);
        pta.addCaretListener(this);
        pta.addCaretListener(this);
        pta.getDocument().addUndoableEditListener(undoHandler);
        JScrollPane scroller = new JScrollPane();
        JViewport port = scroller.getViewport();
        port.add(pta);
        fr.getContentPane().add("Center", scroller);
        fr.getContentPane().add("South", p);
        p.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0));
        p.add(fileStatus);
        p.add(statusRow);
        p.add(statusCol);
        p.add(statusMode);
        p.add(statusSize);

        // 初始化菜单栏
        JMenuBar mb = new JMenuBar();

        // 初始化File菜单
        JMenu menuFile = new JMenu("File", true);
        menuFile.setMnemonic('F');

        // 初始化New菜单项
        menuFileNew = new JMenuItem("New", 'N');
        menuFileNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
                InputEvent.CTRL_MASK));
        menuFileNew.addActionListener(this);

        // 初始化Open菜单项
        menuFileOpen = new JMenuItem("Open...", 'O');
        menuFileOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
                InputEvent.CTRL_MASK));
        menuFileOpen.addActionListener(this);

        // 初始化Close菜单项
        menuFileClose = new JMenuItem("Close", 'C');
        menuFileClose.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4,
                InputEvent.CTRL_MASK));
        menuFileClose.addActionListener(this);

        // 初始化Save菜单项
        menuFileSave = new JMenuItem("Save", 'S');
        menuFileSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
                InputEvent.CTRL_MASK));
        menuFileSave.addActionListener(this);

        // 初始化Save as菜单项
        menuFileSaveAs = new JMenuItem("Save As...", 'A');
        menuFileSaveAs.setAccelerator(KeyStroke
                .getKeyStroke(KeyEvent.VK_F12, 0));
        menuFileSaveAs.addActionListener(this);

        // 初始化Print菜单项
        menuFilePrint = new JMenuItem("Print", 'P');
        menuFilePrint.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,
                InputEvent.CTRL_MASK));
        menuFilePrint.addActionListener(this);
        menuFilePrint.setEnabled(false);

        // 初始化Print Setup菜单项
        menuFilePrintSetup = new JMenuItem("Print Setup...");
        menuFilePrintSetup.addActionListener(this);
        menuFilePrintSetup.setMnemonic('u');
        menuFilePrintSetup.setEnabled(false);

        // 初始化Exit菜单项
        menuFileExit = new JMenuItem("Exit", 'x');
        menuFileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
                InputEvent.CTRL_MASK));
        menuFileExit.addActionListener(this);

        // 初始化Edit菜单项
        JMenu menuEdit = new JMenu("Edit", true);

        // 初始化Undo菜单项
        menuEditUndo = new JMenuItem("Undo");
        menuEditUndo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z,
                InputEvent.CTRL_MASK));
        menuEditUndo.addActionListener(this);
        menuEditUndo.setEnabled(false);

        // 初始化Redo菜单项
        menuEditRedo = new JMenuItem("Redo");
        menuEditRedo.addActionListener(this);
        menuEditRedo.setEnabled(false);

        // 初始化Cut菜单项
        menuEditCut = new JMenuItem("Cut", 't');
        menuEditCut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
                InputEvent.CTRL_MASK));
        menuEditCut.addActionListener(this);

        // 初始化Copy菜单项
        menuEditCopy = new JMenuItem("Copy", 'C');
        menuEditCopy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,
                InputEvent.CTRL_MASK));
        menuEditCopy.addActionListener(this);

        // 初始化Paste菜单项
        menuEditPaste = new JMenuItem("Paste", 'P');
        menuEditPaste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,
                InputEvent.CTRL_MASK));
        menuEditPaste.addActionListener(this);

        // 初始化Delete菜单项
        JMenu menuEditDelete = new JMenu("Delete");
        menuEditDelete.setMnemonic('D');

        // 初始化Selection菜单项
        menuEditDeleteSelection = new JMenuItem("Selection", 'S');
        menuEditDeleteSelection.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_DELETE, InputEvent.CTRL_MASK));
        menuEditDeleteSelection.addActionListener(this);

        // 初始化Line菜单项
        menuEditDeleteLine = new JMenuItem("Line", 'L');
        menuEditDeleteLine.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y,
                InputEvent.CTRL_MASK));
        menuEditDeleteLine.addActionListener(this);

        // 初始化Word菜单项
        menuEditDeleteWord = new JMenuItem("Word", 'W');
        menuEditDeleteWord.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D,
                InputEvent.CTRL_MASK));
        menuEditDeleteWord.addActionListener(this);

        // 初始化Find菜单项
        menuEditFind = new JMenuItem("Find...", 'F');
        menuEditFind.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F,
                InputEvent.CTRL_MASK));
        menuEditFind.addActionListener(this);

        // 初始化Replace菜单项
        menuEditReplace = new JMenuItem("Replace...", 'R');
        menuEditReplace.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H,
                InputEvent.CTRL_MASK));
        menuEditReplace.addActionListener(this);
        menuEditReplace.setEnabled(false);

        // 初始化Goto菜单项
        menuEditGoTo = new JMenuItem("GoTo...", 'G');
        menuEditGoTo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G,
                InputEvent.CTRL_MASK));
        menuEditGoTo.addActionListener(this);

        // 初始化SelectAll菜单项
        menuEditSelectAll = new JMenuItem("Select All", 'A');
        menuEditSelectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A,
                InputEvent.CTRL_MASK));
        menuEditSelectAll.addActionListener(this);

        // 初始化View菜单项
        JMenu menuView = new JMenu("View", true);

        // 初始化Font菜单项
        menuViewFont = new JMenuItem("Font...", 'F');
        menuViewFont.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F,
                InputEvent.CTRL_MASK + InputEvent.ALT_MASK));
        menuViewFont.addActionListener(this);

        // 初始化Color菜单项
        menuViewColor = new JMenuItem("Color...", 'C');
        menuViewColor.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
                InputEvent.CTRL_MASK + InputEvent.ALT_MASK));
        menuViewColor.addActionListener(this);

        // 初始化Classic菜单项
        menuViewClassic = new JCheckBoxMenuItem("Classic");
        menuViewClassic.setMnemonic('1');
        menuViewClassic.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L,
                InputEvent.CTRL_MASK + InputEvent.ALT_MASK));
        menuViewClassic.addActionListener(this);
        menuViewClassic.setState(false);

        // 初始化Status菜单项
        menuViewStatus = new JCheckBoxMenuItem("Status");
        menuViewStatus.setMnemonic('S');
        menuViewStatus.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
                InputEvent.CTRL_MASK + InputEvent.ALT_MASK));
        menuViewStatus.addActionListener(this);
        menuViewStatus.setState(true);

        // 初始化Word Wrap菜单项
        menuViewWordWrap = new JCheckBoxMenuItem("Word Wrap");
        menuViewWordWrap.setMnemonic('W');
        menuViewWordWrap.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
                InputEvent.CTRL_MASK + InputEvent.ALT_MASK));
        menuViewWordWrap.addActionListener(this);
        menuViewWordWrap.setState(false);

        // 初始化Double Space菜单项
        menuViewDoubleSpace = new JMenuItem("Double Space", 'D');
        menuViewDoubleSpace.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_O, InputEvent.CTRL_MASK + InputEvent.ALT_MASK));
        menuViewDoubleSpace.addActionListener(this);

        // 初始化Help菜单项
        JMenu menuHelp = new JMenu("Help", true);

        // 初始化About菜单项
        menuHelpAbout = new JMenuItem("About", 'A');
        menuHelpAbout.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
        menuHelpAbout.addActionListener(this);

        // 添加菜单
        fr.setJMenuBar(mb);
        mb.add(menuFile);
        menuFile.add(menuFileNew);
        menuFile.add(menuFileOpen);
        menuFile.add(menuFileClose);
        menuFile.addSeparator();
        menuFile.add(menuFileSave);
        menuFile.add(menuFileSaveAs);
        menuFile.addSeparator();
        menuFile.add(menuFilePrint);
        menuFile.add(menuFilePrintSetup);
        menuFile.addSeparator();
        menuFile.add(menuFileExit);

        mb.add(menuEdit);
        menuEdit.add(menuEditUndo);
        menuEdit.add(menuEditRedo);
        menuFile.addSeparator();
        menuEdit.add(menuEditCut);
        menuEdit.add(menuEditCopy);
        menuEdit.add(menuEditPaste);
        menuEdit.add(menuEditDelete);

        menuEditDelete.add(menuEditDeleteSelection);
        menuEditDelete.add(menuEditDeleteLine);
        menuEditDelete.add(menuEditDeleteWord);
        menuEdit.addSeparator();
        menuEdit.add(menuEditFind);
        menuEdit.add(menuEditReplace);
        menuEdit.add(menuEditGoTo);
        menuEdit.addSeparator();
        menuEdit.add(menuEditSelectAll);

        mb.add(menuView);
        menuView.add(menuViewFont);
        menuView.add(menuViewColor);
        menuView.addSeparator();
        menuView.add(menuViewClassic);
        menuView.add(menuViewStatus);
        menuView.add(menuViewWordWrap);
        menuView.addSeparator();
        menuView.add(menuViewDoubleSpace);

        mb.add(menuHelp);
        menuHelp.add(menuHelpAbout);

        fr.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        fr.setSize(600, 420);
        fr.setVisible(true);
    }

    // 事件监听方法
    public void actionPerformed(ActionEvent e) {
        // 文件菜单事件响应
        if (e.getSource() == menuFileNew) {
            // 新建文件
            pta.replaceRange("", 0, pta.getText().length());
            fns = null;
            fileStatus.setText("New File");
            undo.discardAllEdits();
            menuEditUndo.setEnabled(false);
        } else if (e.getSource() == menuFileOpen) {
            // 打开文件
            String s = null;
            StringBuffer strPool = new StringBuffer();
            Frame openFileFrame = new Frame("Open file");
            FileDialog fileDialog = new FileDialog(openFileFrame);
            fileDialog.setMode(FileDialog.LOAD);
            fileDialog.setFile("*.txt;*.java");
            fileDialog.show();
            String file = fileDialog.getFile();
            String dir = fileDialog.getDirectory();
            // 读取文件
            if (file != null) {
                fns = dir + file;
                pta.replaceRange("", 0, pta.getText().length());
                BufferedReader br;
                try {
                    br = new BufferedReader(new FileReader(fns));
                    s = br.readLine();
                    while (s != null) {
                        strPool.append(s + '\15' + '\12');
                        s = br.readLine();
                    }
                    br.close();
                    pta.setText(strPool.toString());
                } catch (IOException ie) {

                }
                // 显示状态
                fileStatus.setText("File opened.");
                isNewFile = true;
                undo.discardAllEdits();
                menuEditUndo.setEnabled(false);
            }
        } else if (e.getSource() == menuFileClose) {
            // 关闭文件
            pta.replaceRange("", 0, pta.getText().length());
            fileStatus.setText("File closed without save");
            undo.discardAllEdits();
            menuEditUndo.setEnabled(false);
            fns = null;
        } else if (e.getSource() == menuFilePrint) {
            // 打印文件
            JOptionPane.showMessageDialog(null,
                    "TODO... Only the FIRST page Now.", "Print", 1);
            pta.printIt(pta.getText(), pta.getFont());
        } else if (e.getSource() == menuFileSave) {
            // 保存文件
            OutputStreamWriter osw;
            if (fns != null) {
                try {
                    osw =
                            new OutputStreamWriter(new BufferedOutputStream(
                                    new FileOutputStream(fns)));
                    osw.write(pta.getText(), 0, pta.getText().length());
                    osw.close();
                    fileStatus.setText("file saved");
                } catch (IOException ie) {

                }
                if (fileStatus.getText().endsWith("*")) {
                    fileStatus.setText(fileStatus.getText().substring(0,
                            fileStatus.getText().length() - 1));
                }
            } else {
                Frame saveFileFrame = new Frame("Save file");
                FileDialog fileDialog = new FileDialog(saveFileFrame);
                fileDialog.setMode(FileDialog.SAVE);
                fileDialog.setFile("*.txt;*.java");
                fileDialog.show();
                String file = fileDialog.getFile();
                String dir = fileDialog.getDirectory();
                if (file != null) {
                    fns = dir + file;
                    try {
                        osw =
                                new OutputStreamWriter(
                                        new BufferedOutputStream(
                                                new FileOutputStream(fns)));
                        osw.write(pta.getText(), 0, pta.getText().length());
                        osw.close();
                        fileStatus.setText("File saved");
                    } catch (IOException ie) {

                    }
                }

            }
        } else if (e.getSource() == menuFileSaveAs) {
            // 另存为
            OutputStreamWriter osw;
            Frame saveFileFrame = new Frame("Save file");
            FileDialog fileDialog = new FileDialog(saveFileFrame);
            fileDialog.setMode(FileDialog.SAVE);
            fileDialog.setFile("*.txt;*.java");
            fileDialog.show();
            String file = fileDialog.getFile();
            String dir = fileDialog.getDirectory();
            if (file != null) {
                fns = dir + file;
                try {
                    osw =
                            new OutputStreamWriter(new BufferedOutputStream(
                                    new FileOutputStream(fns)));
                    osw.write(pta.getText(), 0, pta.getText().length());
                    osw.close();
                    fileStatus.setText("File saved");
                } catch (IOException ie) {

                }
            }
        } else if (e.getSource() == menuFileExit) {
            // 退出
            System.exit(0);
        }
        // 编辑菜单事件响应
        else if (e.getSource() == menuEditUndo) {
            // 撤销
            if (undo.canUndo()) {
                try {
                    undo.undo();
                } catch (CannotUndoException cue) {
                    System.out.println("Unable to undo: " + cue);
                    cue.printStackTrace();
                }
                if (!undo.canUndo()) {
                    menuEditUndo.setEnabled(false);
                }
            } else {
                menuEditUndo.setEnabled(false);
            }
        } else if (e.getSource() == menuEditRedo) {
            // 重复
            // TODO 未实现
        } else if (e.getSource() == menuEditCut) {
            // 剪切
            pta.cut();
        } else if (e.getSource() == menuEditCopy) {
            // 复制
            pta.copy();
        } else if (e.getSource() == menuEditPaste) {
            // 粘贴
            pta.paste();
        } else if (e.getSource() == menuEditDeleteSelection) {
            // 删除
            pta.replaceRange("", pta.getSelectionStart(), pta.getSelectionEnd());
        } else if (e.getSource() == menuEditDeleteLine) {
            // 删除行
            String str = pta.getText();
            int pos = pta.getCaretPosition();
            int lineStart = 0, lineEnd = 0;
            lineStart = str.substring(0, pos).lastIndexOf('\12');
            lineEnd = str.indexOf('\15', pos);
            lineStart = (lineStart == -1) ? 0 : (lineStart - 1);
            pta.replaceRange("", lineStart, lineEnd);
            lineStart = (lineStart == 0) ? 0 : (lineStart + 2);
            pta.setCaretPosition(lineStart);
        } else if (e.getSource() == menuEditDeleteWord) {
            // 删除单词
            String str = pta.getText();
            int pos = pta.getCaretPosition();
            int wordStart = 0, wordEnd = 0;
            wordEnd = wordLocation(str, pos, true);
            if (wordEnd == pos) {
                wordStart = pos;
                wordEnd = pos + 1;
                pta.replaceRange("", wordStart, wordEnd);
            } else {
                wordStart = wordLocation(str, pos, false);
                if (wordStart == -1) {
                    pta.replaceRange("", 0, wordEnd);
                } else {
                    pta.replaceRange("", wordStart, wordEnd);
                }
            }
        } else if (e.getSource() == menuEditFind) {
            // 查找
            // 创建Find查找对话框
            JDialog ds = new JDialog(this, "Find", true);
            ds.getContentPane().setLayout(new FlowLayout());
            ds.setResizable(false);
            tfs = new TextField(15);
            ds.getContentPane().add(tfs);
            bs = new Button("Find");
            bs.addActionListener(this);
            Button bsc = new Button("Cancel");
            bsc.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent bOKe) {
                    dispose();
                    foundCount = 0;
                }
            });
            ds.getContentPane().add(bs);
            ds.getContentPane().add(bsc);
            JLabel dsMessage1 = new JLabel("Found counts: ");
            dsMessage2 = new JLabel("0");
            dsLoop = new Checkbox("Loop");
            dsLoop.setState(findingLoop);
            dsMatchCase = new Checkbox("Match Case");
            ds.getContentPane().add(dsLoop);
            ds.getContentPane().add(dsMatchCase);
            ds.getContentPane().add(dsMessage1);
            ds.getContentPane().add(dsMessage2);
            ds.setLocation(120, 120);
            ds.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    dispose();
                    FindStartPos = 0;
                }
            });
            // 显示Find对话框
            ds.setSize(250, 110);
            ds.setVisible(true);
        } else if (e.getSource() == bs) {
            //
            int a = 0, b = 0;
            String str1, str2, str3, str4, strA, strB;
            str1 = pta.getText();
            str2 = str1.toLowerCase();
            str3 = tfs.getText();
            str4 = str3.toLowerCase();
            if (dsMatchCase.getState()) {
                strA = str1;
                strB = str3;
            } else {
                strA = str2;
                strB = str4;
            }
            a = strA.indexOf(strB, FindStartPos);
            if (a > -1) {
                pta.setCaretPosition(a);
                b = tfs.getText().length();
                pta.select(a, a + b);
                FindStartPos = a + b;
                foundCount++;
                dsMessage2.setText(foundCount + "");
            } else {
                if (dsLoop.getState()) {
                    JOptionPane.showMessageDialog(null, "End of file.",
                            "Find result", 1);
                } else {
                    JOptionPane.showMessageDialog(null, "End of file.",
                            "Find result", 1);
                }
                foundCount = 0;
            }
        } else if (e.getSource() == menuEditReplace) {
            // 替换
            // 创建Replace替换对话框
            JDialog dr = new JDialog(this, "Replace", true);
            dr.getContentPane().setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.gridwidth = 2;
            gbc.gridheight = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.anchor = GridBagConstraints.CENTER;
            Panel p1 = new Panel();
            dr.getContentPane().add(p1);
            drMatchCase = new Checkbox("Match Case");
            gbc.gridx = 1;
            gbc.gridy = 1;
            gbc.gridwidth = 1;
            gbc.gridheight = 1;
            dr.getContentPane().add(drMatchCase);
            gbc.gridx = 2;
            gbc.gridy = 0;
            gbc.gridwidth = 1;
            gbc.gridheight = 1;
            gbc.fill = GridBagConstraints.NONE;
            gbc.anchor = GridBagConstraints.EAST;
            Panel p2 = new Panel();
            p1.setLayout(new GridLayout(5, 1));

            // 设置布局方式
            p2.setLayout(new GridLayout(4, 1));
            dr.getContentPane().add(p2);
            JLabel drMessage1 = new JLabel("Replace: ");
            JLabel drMessage2 = new JLabel("Width: ");
            drMatchCase = new Checkbox("Match Case");
            tfro = new TextField(15);
            tfrn = new TextField(15);
            p1.add(drMessage1);
            p1.add(tfro);
            p1.add(drMessage2);
            p1.add(tfrn);
            p1.add(drMatchCase);

            // 加入监听器
            brf = new Button("Find");
            brf.addActionListener(this);
            brf.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    int a = 0, b = 0;
                    String str1, str2, str3, str4, strA, strB;
                    str1 = pta.getText();
                    str2 = str1.toLowerCase();
                    str3 = tfro.getText();
                    str4 = str3.toLowerCase();
                    if (drMatchCase.getState()) {
                        strA = str1;
                        strB = str3;
                    } else {
                        strA = str2;
                        strB = str4;
                    }
                    a = strA.indexOf(strB, FindStartPos);
                    if (a > -1) {
                        pta.setCaretPosition(a);
                        b = tfro.getText().length();
                        pta.select(a, a + b);
                        FindStartPos = a + b;
                        foundCount++;
                    } else {
                        JOptionPane.showMessageDialog(null, "End of file.",
                                "Result", 1);
                        foundCount = 0;
                    }
                }
            });
            brr = new Button("Replace");

            // 加入监听器
            brr.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    if (tfrn.getText().length() == 0
                            && pta.getSelectedText() != null) {
                        pta.replaceSelection("");
                    }
                    if (tfrn.getText().length() > 0
                            && pta.getSelectedText() != null) {
                        pta.replaceSelection(tfrn.getText());
                    }
                    int a = 0, b = 0;
                    String str1, str2, str3, str4, strA, strB;
                    str1 = pta.getText();
                    str2 = str1.toLowerCase();
                    str3 = tfro.getText();
                    str4 = str3.toLowerCase();
                    if (drMatchCase.getState()) {
                        strA = str1;
                        strB = str3;
                    } else {
                        strA = str2;
                        strB = str4;
                    }
                    a = strA.indexOf(strB, FindStartPos);
                    if (a > -1) {
                        pta.setCaretPosition(a);
                        b = tfro.getText().length();
                        pta.select(a, a + b);
                        FindStartPos = a + b;
                        foundCount++;
                    } else {
                        JOptionPane.showMessageDialog(null, "End of file.",
                                "Result", 1);
                        foundCount = 0;
                    }
                }
            });

            brra = new Button("Replace All");

            // 加入监听器
            brra.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    int a = 0;
                    while (a > -1) {
                        int b = 0;
                        String str1, str2, str3, str4, strA, strB;
                        str1 = pta.getText();
                        str2 = str1.toLowerCase();
                        str3 = tfro.getText();
                        str4 = str3.toLowerCase();
                        if (drMatchCase.getState()) {
                            strA = str1;
                            strB = str3;
                        } else {
                            strA = str2;
                            strB = str4;
                        }
                        a = strA.indexOf(strB, FindStartPos);
                        if (a > -1) {
                            pta.setCaretPosition(a);
                            b = tfro.getText().length();
                            pta.select(a, a + b);
                            FindStartPos = a + b;
                            foundCount++;
                        } else {
                            JOptionPane.showMessageDialog(null, "End offile.",
                                    "Result", 1);;
                            foundCount = 0;
                        }
                        if (tfrn.getText().length() == 0
                                && pta.getSelectedText() != null) {
                            pta.replaceSelection("");
                        }
                        if (tfrn.getText().length() > 0
                                && pta.getSelectedText() != null) {
                            pta.replaceSelection(tfrn.getText());
                        }
                    }
                }
            });

            Button brc = new Button("Cancel");

            // 加入监听器
            brc.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    dispose();
                }
            });
            p2.add(brf);
            p2.add(brr);
            p2.add(brra);
            p2.add(brc);
            dr.setResizable(false);
            dr.setLocation(120, 120);
            dr.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    dispose();
                    FindStartPos = 0;
                }
            });
            dr.setSize(220, 138);
            // 显示替换查找对话框
            dr.setVisible(true);

        } else if (e.getSource() == menuEditGoTo) {
            // GoTo操作
            JDialog dg = new JDialog(this, "Line Number", true);
            dg.getContentPane().setLayout(new FlowLayout());
            final JTextField dgtf = new JTextField(4);
            Button dgOK = new Button("To To");

            // 加入监听器
            dgOK.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    int totalLine = pta.getLineCount();
                    int[] lineNumber = new int[totalLine + 1];
                    String s = pta.getText();
                    int pos = 0, t = 0;
                    while (true) {
                        pos = s.indexOf('\12', pos);
                        if (pos == -1) {
                            break;
                        }
                        lineNumber[t++] = pos++;
                    }
                    int gt = 1;
                    try {
                        gt = Integer.parseInt(dgtf.getText());
                    } catch (NumberFormatException efe) {
                        JOptionPane.showMessageDialog(null,
                                "Please input an integer", "input", 1);
                    }
                    if (gt < 2 || gt >= totalLine) {
                        if (gt < 2) {
                            pta.setCaretPosition(0);
                        } else {
                            pta.setCaretPosition(s.length());
                        }
                    } else {
                        pta.setCaretPosition(lineNumber[gt - 2] + 1);
                    }
                    dispose();
                }
            });

            Button dgCancel = new Button("Cancel");
            // 加入监听器
            dgCancel.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    dispose();
                }
            });
            dg.getContentPane().add(dgtf);
            dg.getContentPane().add(dgOK);
            dg.getContentPane().add(dgCancel);
            dg.setResizable(false);
            dg.setLocation(120, 120);
            dg.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    dispose();
                }
            });
            dg.setSize(180, 60);
            dg.setVisible(true);

        } else if (e.getSource() == menuEditSelectAll) {
            // 选择全部
            pta.selectAll();
        }
        // 视图菜单事件响应
        else if (e.getSource() == menuViewFont) {
            // 字体
            MenuFont mf = new MenuFont(this, true);
            pta.setFont(mf.myLayout(pta.getFont()));
        } else if (e.getSource() == menuViewColor) {
            // 颜色
            MenuColor mc = new MenuColor(this, true);
            Color[] fbgc = new Color[2];
            fbgc = mc.myLayout(pta.getForeground(), pta.getBackground());
            pta.setForeground(fbgc[0]);
            pta.setBackground(fbgc[1]);
            pta.setCaretColor(fbgc[0]);
        } else if (e.getSource() == menuViewClassic) {
            // 经典模式
            if (menuViewClassic.getState()) {
                pta.setForeground(new Color(0, 255, 0));
                pta.setBackground(new Color(45, 0, 45));
                pta.setFont(new Font("Serif", Font.BOLD, 16));
                pta.setCaretColor(new Color(0, 255, 0));
            } else {
                pta.setForeground(defaultForeground);
                pta.setBackground(defaultBackground);
                pta.setFont(defaultFont);
                pta.setCaretColor(defaultCaretColor);
            }
        } else if (e.getSource() == menuViewStatus) {
            // 状态
            if (menuViewStatus.getState()) {
                showStatus();
            } else if (e.getSource() == menuViewWordWrap) {
                if (menuViewWordWrap.getState()) {
                    pta.setLineWrap(true);
                } else {
                    pta.setLineWrap(false);
                }
            }
        } else if (e.getSource() == menuViewWordWrap) {
            //
            if (menuViewWordWrap.getState()) {
                pta.setLineWrap(true);
            } else {
                pta.setLineWrap(false);
            }
        } else if (e.getSource() == menuViewDoubleSpace) {
            //
            int pos = 0;
            String str = pta.getText();
            while (true) {
                pos = str.indexOf('\15', pos);
                if (pos == -1) {
                    break;
                }
                str =
                        str.substring(0, pos) + '\15' + '\12'
                                + str.substring(pos);
                pos += 3;
            }
            pta.setText(str);
        }
        // 帮助菜单事件响应
        else if (e.getSource() == menuHelpAbout) {
            // 关于
            // 创建About对话框
            dl = new JDialog(this, "About MiniEditor", true);
            dl.getContentPane().setLayout(new GridLayout(3, 3));
            dl.setBackground(new Color(212, 208, 200));
            Button bOK = new Button("OK");

            // 加入监听器
            bOK.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    dispose();
                }
            });
            Label ver = new Label("Version 1.0");
            Label null1 = new Label();
            Label null2 = new Label();
            Label null3 = new Label();
            Label null4 = new Label();
            Label null5 = new Label();
            Label null6 = new Label();
            Label null7 = new Label();
            dl.getContentPane().add(null1);
            dl.getContentPane().add(ver);
            dl.getContentPane().add(null2);
            dl.getContentPane().add(null3);
            dl.getContentPane().add(bOK);
            dl.getContentPane().add(null3);
            dl.getContentPane().add(null4);
            dl.getContentPane().add(null5);
            dl.getContentPane().add(null6);
            dl.getContentPane().add(null7);
            bOK.addActionListener(this);
            dl.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    dispose();
                }
            });
            dl.setLocation(120, 120);
            dl.setResizable(false);
            dl.setSize(200, 80);

            // 显示About对话框
            dl.setVisible(true);
        }

    }

    // 键盘监听方法
    public void keyTyped(KeyEvent e) {
        beginTextListener = true;
        isNewFile = false;
        if (!BACKSPACE) {
            int pos = pta.getCaretPosition();
            char c = pta.getText().charAt(pos);
            if (c == '\12') {

            } else if (c == '\15') {

            } else {
                pta.replaceRange("", pos, pos + 1);
            }
        }
        BACKSPACE = false;
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == '\10') {
            BACKSPACE = true;
        }
    }

    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == 155) {
            if (INSERTMODE) {
                INSERTMODE = false;
            } else {
                INSERTMODE = true;
            }
        }
        if (menuViewStatus.getState()) {
            showStatus();
        }
    }

    public void removeUpdate(DocumentEvent de) {
        String s;
        s = fileStatus.getText();
        if (!s.endsWith("*") & beginTextListener & !isNewFile) {
            fileStatus.setText("*");
        }
        menuEditUndo.setEnabled(true);
    }

    public void insertUpdate(DocumentEvent de) {
        String s;
        s = fileStatus.getText();
        if (!s.endsWith("*") & beginTextListener & !isNewFile) {
            fileStatus.setText("*");
        }
        menuEditUndo.setEnabled(true);
    }

    public void changeUpdate(DocumentEvent de) {
        String s;
        s = fileStatus.getText();
        if (!s.endsWith("*") & beginTextListener & !isNewFile) {
            fileStatus.setText("*");
        }
        menuEditUndo.setEnabled(true);
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        // TODO Auto-generated

    }

    // caret监听方法
    public void caretUpdate(CaretEvent ce) {
        if (menuViewStatus.getState()) {
            showStatus();
        }
    }

    // 显示当前光标位置及编辑属性
    public void showStatus() {
        int rows, cols, from, current, to, fileSize;
        rows = cols = from = current = 0;
        to = pta.getCaretPosition();
        fileSize = 0;
        String str = pta.getText();
        cols = to - str.substring(0, to).lastIndexOf(10);
        fileSize = str.length();
        String mode;
        if (INSERTMODE) {
            mode = "INSERT";
        } else {
            mode = "OVERLAY";
        }
        try {
            rows = pta.getLineOfOffset(to) + 1;
        } catch (BadLocationException ble) {

        }
        statusRow.setText("Row: " + rows);
        statusCol.setText("Col: " + cols);
        statusMode.setText("Mode: " + mode);
        statusSize.setText("Size: " + fileSize);
    }

    // 单词定位方法
    int wordLocation(String str, int pos, boolean isToRight) {
        char c;
        if (isToRight) {
            c = str.charAt(pos);
            while (true) {
                if (c < 48) {
                    break;
                } else if (c > 57 & c < 65) {
                    break;
                } else if (c > 90 & c < 97) {
                    break;
                } else if (c > 122) {
                    break;
                }
                pos++;
                c = str.charAt(pos);
            }
            return pos--;
        } else {
            pos--;
            c = str.charAt(pos);
            while (true) {
                if (c < 48) {
                    break;
                } else if (c > 57 & c < 65) {
                    break;
                } else if (c > 97 & c < 97) {
                    break;
                } else if (c > 122) {
                    break;
                }
                pos--;
                c = str.charAt(pos);
            }
            return pos++;
        }
    }

    // UndoHandler的声明
    class UndoHandler implements UndoableEditListener {

        @Override
        public void undoableEditHappened(UndoableEditEvent e) {
            undo.addEdit(e.getEdit());
        }

    }
}
